<template>
  <div>
    <a-layout id="components-layout-demo-custom-trigger">
      <a-layout-sider :width="widthLeftForTools" :trigger="null" collapsible>
        <div class="logo">
          <a-icon type="fund"/>
          <span style="margin-left: 10px;">大屏设计器</span>
        </div>
        <a-menu theme="dark" mode="inline">
          <a-menu-item style="text-align: center;padding-left:16px;margin: 0;">
            <span>图层</span>
          </a-menu-item>
          <a-menu-item v-for="(item, index) in layerWidget" @click="layerClick(index)">
            <a-icon :type="item.icon" />
            <span>{{ item.label }}</span>
          </a-menu-item>
        </a-menu>
      </a-layout-sider>
      <a-layout>
        <a-layout-header style="padding: 0">
          <a-menu mode="horizontal" class="menu-tools" triggerSubMenuAction="click">
            <a-sub-menu v-for="wtype in widgetTypes">
              <span slot="title" class="submenu-title-wrapper"><a-icon class="trigger" :type="wtype.icon" /></span>
              <a-menu-item-group v-for="category in wtype.categorys">
                <span slot="title" class="submenu-title-wrapper"><a-icon class="trigger" :type="category.icon" /> {{category.lable}}</span>
                <a-card>
                  <a-card-grid style="width:auto;text-align:center;padding:4px;" :key="widget.code" v-for="widget in widgetTools.filter(item => {return item.type == category.code})" @click="evt => widgetOnDragged(evt, widget.code)">
                    <img :src="widget.preview" style="width:100px;height:55px;"/>
                    <p>{{ widget.label }}</p>
                  </a-card-grid>
                </a-card>
              </a-menu-item-group>
            </a-sub-menu>
          </a-menu>
          <a-divider type="vertical" />
          <a-tooltip title="保存">
            <a-icon class="trigger" type="save" @click="saveData"/>
          </a-tooltip>
          <a-tooltip title="预览">
            <a-icon class="trigger" type="eye" @click="viewScreen"/>
          </a-tooltip>
          <a-tooltip title="导出">
            <a-icon class="trigger" type="download"/>
          </a-tooltip>
        </a-layout-header>
        <a-layout>
          <a-layout-content>
            <div class="workbench-container" :style="{ width: middleWidth + 'px', height: middleHeight + 'px'}">
              <vue-ruler-tool
                v-model="dashboard.presetLine"
                class="vueRuler"
                :step-length="100"
                :parent="true"
                :position="'relative'"
                :is-scale-revise="true"
                :visible.sync="dashboard.presetLineVisible"
                style="padding: 10px;"
              >
                <div
                  ref="workbench"
                  class="workbench"
                  :style="{
                    width: bigscreenWidthInWorkbench + 'px',
                    height: bigscreenHeightInWorkbench + 'px',
                    position: 'absolute',
                    zIndex: -1,
                    'background-color': dashboard.backgroundColor,
                    'background-image': 'url(' + dashboard.backgroundImage + ')',
                    'background-position': '0% 0%',
                    'background-size': '100% 100%',
                    'background-repeat': 'initial',
                    'background-attachment': 'initial',
                    'background-origin': 'initial',
                    'background-clip': 'initial'
                  }"
                  @click.self="setOptionsOnClickScreen"
                >
                  <div v-if="grade" class="bg-grid"></div>
                  <widget
                    ref="widgets"
                    v-for="(widget, index) in widgets"
                    :key="index"
                    v-model="widget.value"
                    :index="index"
                    :step="step"
                    :type="widget.type"
                    :bigscreen="{ bigscreenWidth, bigscreenHeight }"
                    @onActivated="setOptionsOnClickWidget"
                    @contextmenu.prevent.native="rightClick($event, index)"
                    @mousedown.prevent.native="widgetsClick(index)"
                    @mouseup.prevent.native="widgetsMouseup"
                  />
                </div>
              </vue-ruler-tool>
            </div>
          </a-layout-content>
        </a-layout>
      </a-layout>
      <a-layout-sider :width="widthLeftForOptions">
        <div class="logo" style="text-align: left;">
          <a-icon class="trigger" type="setting"/>
          <span style="margin-left: 10px;">配置项设置</span>
        </div>
        <a-tabs v-model="activeName" default-active-key="配置">
          <a-tab-pane key="配置" force-render v-if="(widgetOptions.setup && widgetOptions.setup.length > 0) || (widgetOptions.collapse && widgetOptions.collapse.length > 0)">
            <div slot="tab" class="setting-tab-title">配置</div>
            <dynamicForm ref="formData" :options="widgetOptions.setup" @onChanged="val => widgetValueChanged('setup', val)"/>
          </a-tab-pane>
          <a-tab-pane key="数据" force-render v-if="widgetOptions.data && widgetOptions.data.length > 0">
            <div slot="tab" class="setting-tab-title">数据</div>
            <dynamicForm ref="formData" :options="widgetOptions.data" @onChanged="val => widgetValueChanged('data', val)"/>
          </a-tab-pane>
          <a-tab-pane key="坐标" force-render v-if="widgetOptions.position && widgetOptions.position.length > 0">
            <div slot="tab" class="setting-tab-title">坐标</div>
            <dynamicForm ref="formData" :options="widgetOptions.position" @onChanged="val => widgetValueChanged('position', val)"/>
          </a-tab-pane>
        </a-tabs>
      </a-layout-sider>
    </a-layout>
    <content-menu :visible.sync="visibleContentMenu" :style-obj="styleObj" @deletelayer="deletelayer" @copylayer="copylayer" @istopLayer="istopLayer" @setlowLayer="setlowLayer" @moveupLayer="moveupLayer" @movedownLayer="movedownLayer" />
  </div>
</template>

<script>
import { getAction, httpAction } from '@/api/manage'
import { cloneObject } from "@/utils/util"
import { widgetTools, getToolByCode } from "./tools/index";
import widget from "./widget/widget";
import dynamicForm from "./designerComponents/dynamicForm.vue";
import draggable from "vuedraggable";
import VueRulerTool from "vue-ruler-tool";
import contentMenu from "./designerComponents/contentMenu";

export default {
  name: "AjReportScreenDesignerIndex",
  components: {
    draggable,
    VueRulerTool,
    widget,
    dynamicForm,
    contentMenu
  },
  data() {
    return {
      collapsed: false,
      dropdowns: {},
      grade: false,
      layerWidget: [],
      widgetTools: widgetTools, // 左侧工具栏的组件图标，将js变量加入到当前作用域
      widthLeftForTools: 200, // 左侧工具栏宽度
      widthLeftForOptions: 300, // 右侧属性配置区
      topNavTools: 65,
      clientWidth: document.body.clientWidth,
      clientHeight: document.body.clientHeight,
      // 工作台大屏画布，保存到表gaea_report_dashboard中
      defaultDashboard: {
        id: null,
        rcode: this.$route.query.rcode,
        title: '', // 大屏页面标题
        width: 1920, // 大屏设计宽度
        height: 1080, // 大屏设计高度
        backgroundColor: "", // 大屏背景色
        backgroundImage: "", // 大屏背景图片
        refreshSeconds: null, // 大屏刷新时间间隔
        presetLine: null, // 辅助线
        presetLineVisible: true ,// 辅助线是否显示
        widgets: []
      },
      dashboard: {},
      // 大屏的标记
      screenCode: "",
      widgetTypes: [
        {
          code: 'chart',
          icon: 'bar-chart',
          lable: '图表',
          categorys: [
            {
              code: 'barchart',
              icon: 'bar-chart',
              lable: '柱状图'
            },
            {
              code: 'linechart',
              icon: 'line-chart',
              lable: '线型图'
            },
            {
              code: 'piechart',
              icon: 'pie-chart',
              lable: '饼状图'
            },
            {
              code: 'funnel',
              icon: 'heat-map',
              lable: '漏斗图'
            },
            {
              code: 'gauge',
              icon: 'dashboard',
              lable: '仪表盘'
            }
          ]
        },
        {
          code: 'html',
          icon: 'code',
          lable: '页面元素',
          categorys: [
            {
              code: 'text',
              icon: 'font-size',
              lable: '文字'
            },
            {
              code: 'html',
              icon: 'code',
              lable: '页面片段'
            }
          ]
        },
        {
          code: 'ornament',
          icon: 'bg-colors',
          lable: '装饰',
          categorys: [
            {
              code: 'ornament',
              icon: 'border',
              lable: '装饰'
            }
          ]
        },
        {
          code: 'map',
          icon: 'environment',
          lable: '地图'
        },
      ],
      // 大屏画布中的组件
      widgets: [], // 工作区中拖放的组件

      // 当前激活组件
      widgetIndex: 0,
      // 当前激活组件右侧配置属性
      widgetOptions: {
        setup: [], // 配置
        data: [], // 数据
        position: [] // 坐标
      },
      flagWidgetClickStopPropagation: false, // 点击组件时阻止事件冒泡传递到画布click事件上
      styleObj: {
        left: 0,
        top: 0
      },
      visibleContentMenu: false,
      rightClickIndex: -1,
      activeName: "配置",
      url: {
        queryDashboardByRcode: '/ajreport/dashboard/queryByRcode',
        addDashboard: '/ajreport/dashboard/add',
        editDashboard: '/ajreport/dashboard/edit'
      }
    };
  },
  computed: {
    step () {
      return Number(100 / (this.bigscreenScaleInWorkbench * 100))
    },
    bigscreenWidth() {
      return this.dashboard.width
    },
    bigscreenHeight() {
      return this.dashboard.height
    },
    // 折叠切换时，动态计算中间区的宽度
    middleWidth() {
      return this.clientWidth - this.widthLeftForTools - this.widthLeftForOptions
    },
    middleHeight() {
      return this.clientHeight - this.topNavTools;
    },
    // 设计台按大屏的缩放比例
    bigscreenScaleInWorkbench() {
      var widthScale = this.middleWidth / this.bigscreenWidth;
      var heightScale = this.middleHeight / this.bigscreenHeight;
      return Math.min(widthScale, heightScale);
    },
    // 大屏在设计模式的大小
    bigscreenWidthInWorkbench() {
      return this.bigscreenWidth * this.bigscreenScaleInWorkbench;
    },
    bigscreenHeightInWorkbench() {
      return this.bigscreenHeight * this.bigscreenScaleInWorkbench
    },
    workbenchTransform() {
      return `scale(${this.bigscreenScaleInWorkbench}, ${this.bigscreenScaleInWorkbench})`;
    },
  },
  watch: {
    widgets: {
      handler(val) {
        this.handlerLayerWidget(val);
      },
      deep: true
    }
  },
  mounted() {
    // 如果是新的设计工作台
    this.initData();
    window.addEventListener("mouseup", () => {
      this.grade = false;
    });
    window.onresize = () => {
      return (() => {
        this.clientHeight = document.documentElement.clientHeight
        this.clientWidth = document.documentElement.clientWidth
      })()
    };
  },
  methods: {
    fullScreen(flag) {
      this.collapsedTool = flag
      this.collapsedSetting = flag
    },
    widgetsToJson(widgets){
      if(widgets || widgets.length == 0) {
        return []
      }
      console.log(widgets)
      return widgets.map(item => {
        item.options = JSON.parse(item.options)
        item.value = JSON.parse(item.value)
        return item
      })
    },
    initData() {
      const rcode = this.$route.query.rcode;
      if(rcode) {
        getAction(this.url.queryDashboardByRcode, {rcode: rcode}).then(res => {
          if(res.code == 200){
            console.log(res)
            this.dashboard = res.data
            if(res.data.presetLine){
              this.dashboard.presetLine = JSON.parse(res.data.presetLine)
            }
            console.log(this.dashboard, 'this.dashboard')
            console.log(res.data.widgets, 'res.data.widgets')
            if(res.data.widgets){
              this.widgets = this.widgetsToJson(res.data.widgets)
            }
          } else {
            this.dashboard = cloneObject(this.defaultDashboard)
            this.widgets = []
          }
          // 初始化完成后需选中设计面板
          this.setOptionsOnClickScreen();
        })
      } else {
        this.dashboard = cloneObject(this.defaultDashboard)
        this.widgets = []
        // 初始化完成后需选中设计面板
        this.setOptionsOnClickScreen();
      }
    },
    
    // 根据组件列表生成图层
    handlerLayerWidget(widgets) {
      this.layerWidget = widgets.map(item => {
        return {
          icon: getToolByCode(item.type).icon,
          label: item.value.setup.layerName
        }
      })
    },
    // 保存数据
    saveData() {
      console.log(this.dashboard)
      if (!this.widgets || this.widgets.length == 0) {
        this.$message.error("请添加组件");
        return;
      }
      this.mathlayerZindex()
      this.dashboard.widgets = this.widgets
      let httpurl = ''
      let method = ''
      console.log(this.dashboard)
      if (!this.dashboard.id) {
        httpurl += this.url.addDashboard
        method = 'post'
      } else {
        httpurl += this.url.editDashboard
        method = 'put'
      }
      const that = this
      httpAction(httpurl, this.dashboard, method).then((res) => {
        if (res.success) {
          that.$message.success(res.message)
          that.$emit('ok')
        } else {
          that.$message.warning(res.message)
        }
      })
    },
    // 预览
    viewScreen() {
      var router = this.$router.resolve({
        path: "/tool/ajreport/screen/viewer/index",
        query: { rcode: this.$route.query.rcode }
      });
      window.open(router.href, "_blank");
    },
    // 导出
    exportDashboard(val) {
      
    },

    // 在缩放模式下的大小
    getPXUnderScale(px) {
      return this.bigscreenScaleInWorkbench * px;
    },

    // 拖动一个组件放到工作区中去，在拖动结束时，放到工作区对应的坐标点上去
    widgetOnDragged(evt, widgetCode) {
      console.log(evt, '事件对象')
      var tool = getToolByCode(widgetCode);
      var widgetJson = {
        type: widgetCode,
        value: {
          setup: {},
          data: {},
          position: {
            width: 0,
            height: 0,
            left: 0,
            top: 0,
            zIndex: 0
          }
        },
        options: tool.options
      }
      console.log(widgetJson.options)
      widgetJson.options.setup.forEach(item => {
        if(item.type != 'a-divider'){
          widgetJson.value.setup[item.name] = item.value
        }
      })
      widgetJson.options.position.forEach(item => {
        widgetJson.value.position[item.name] = item.value
      })
      if (widgetJson.options.data && widgetJson.options.data.length > 0) {
        widgetJson.options.data.forEach(item => {
          widgetJson.value.data[item.name] = item.value
        })
      }
      console.log(this.widgets, widgetJson)
      this.widgets.push(widgetJson);
      // 激活新组件的配置属性
      this.setOptionsOnClickWidget(this.widgets.length - 1);
    },
    layerClick(index) {
      this.widgetIndex = index;
      this.widgetsClick(index);
    },
    // 如果是点击大屏设计器中的底层，加载大屏底层属性
    setOptionsOnClickScreen() {
      this.screenCode = "screen";
      // 选中不同的组件 右侧都显示第一栏
      this.activeName = "配置";
      this.widgetOptions = getToolByCode("screen")["options"];
    },

    // 如果是点击某个组件，获取该组件的配置项
    setOptionsOnClickWidget(obj) {
      this.screenCode = "";
      if (typeof obj == "number") {
        this.widgetOptions = cloneObject(this.widgets[obj]["options"]);
        return;
      }
      if (obj.index < 0 || obj.index >= this.widgets.length) {
        return;
      }
      this.widgetIndex = obj.index;
      this.widgets[obj.index].value.position = obj;
      this.widgets[obj.index].options.position.forEach(el => {
        for (const key in obj) {
          if (el.name == key) {
            el.value = obj[key];
          }
        }
      });
      this.widgetOptions = cloneObject(this.widgets[obj.index]["options"]);
    },
    widgetsClick(index) {
      const draggableArr = this.$refs.widgets;
      for (let i = 0; i < draggableArr.length; i++) {
        if (i == index) {
          draggableArr[i].$refs.draggable.setActive(true);
        } else {
          draggableArr[i].$refs.draggable.setActive(false);
        }
      }
      this.setOptionsOnClickWidget(index);
      this.grade = true;
      this.collapsedSetting = true
    },
    widgetsMouseup(e) {
      this.grade = false;
    },
    // 将当前选中的组件，右侧属性值更新
    widgetValueChanged(key, val) {
      console.log(key, val)
      if (this.screenCode == "screen") {
        Object.assign(this.dashboard, val)
      } else {
        for (let i = 0; i < this.widgets.length; i++) {
          if (this.widgetIndex == i) {
            this.widgets[i].value[key] = cloneObject(val);
            this.setDefaultValue(this.widgets[i].options[key], val);
          }
        }
      }
    },
    rightClick(event, index) {
      this.rightClickIndex = index;
      const left = event.clientX;
      const top = event.clientY;
      if (left || top) {
        this.styleObj = {
          left: left + "px",
          top: top + "px",
          display: "block"
        };
      }
      this.visibleContentMenu = true;
      return false;
    },
    setDefaultValue(options, val) {
      for (let i = 0; i < options.length; i++) {
        for (const k in val) {
          if (options[i].name == k) {
            options[i].value = val[k]
          }
        }
      }
    },
    mathlayerZindex(){
      this.widgets.forEach((item, index) => {
        item.sort = index
        item.options.position.filter(s => { return s.name == 'zIndex'})[0].value = index
        item.value.position.zIndex = index
      })
    },
    // 删除
    deletelayer() {
      this.widgets.splice(this.rightClickIndex, 1);
      this.$message.success('删除图层成功')
      this.mathlayerZindex()
    },
    // 复制
    copylayer() {
      const obj = cloneObject(this.widgets[this.rightClickIndex]);
      this.widgets.splice(this.widgets.length, 0, obj);
      this.mathlayerZindex()
    },
    // 置顶
    istopLayer() {
      if (this.rightClickIndex + 1 < this.widgets.length) {
        const temp = this.widgets.splice(this.rightClickIndex, 1)[0];
        this.widgets.push(temp);
        this.mathlayerZindex()
      }
    },
    // 置底
    setlowLayer() {
      if (this.rightClickIndex != 0) {
        this.widgets.unshift(this.widgets.splice(this.rightClickIndex, 1)[0]);
        this.mathlayerZindex()
      }
    },
    // 上移一层
    moveupLayer() {
      if (this.rightClickIndex != 0) {
        this.widgets[this.rightClickIndex] = this.widgets.splice(
          this.rightClickIndex - 1,
          1,
          this.widgets[this.rightClickIndex]
        )[0];
      } else {
        this.widgets.push(this.widgets.shift());
      }
      this.mathlayerZindex()
    },
    // 下移一层
    movedownLayer() {
      if (this.rightClickIndex != this.widgets.length - 1) {
        this.widgets[this.rightClickIndex] = this.widgets.splice(
          this.rightClickIndex + 1,
          1,
          this.widgets[this.rightClickIndex]
        )[0];
      } else {
        this.widgets.unshift(this.widgets.splice(this.rightClickIndex, 1)[0]);
      }
      this.mathlayerZindex()
    },
    handleCategoryClick(type, category) {
      console.log(type, category)
      for(let v in this.dropdowns) {
        if(v != category) {
          this.dropdowns[v] = false
        }
      }
      this.dropdowns[type] = true
      this.dropdowns[category] = !this.dropdowns[category]
    },
    visibleChange(visible) {
      if(!visible) {
        for(let v in this.dropdowns) {
          this.dropdowns[v] = false
        }
      }
    }
  }
};
</script>
<style scoped>
  body {
    overflow-y: hidden !important;
  }
</style>

<style lang="less">
  .ant-menu-vertical.ant-menu-sub, .ant-menu-vertical-left.ant-menu-sub, .ant-menu-vertical-right.ant-menu-sub {
    min-width: 100px;
  }
  
  #components-layout-designer-custom-trigger .trigger {
    font-size: 18px;
    line-height: 64px;
    padding: 0 24px;
    cursor: pointer;
    transition: color 0.3s;
  }
  
  #components-layout-designer-custom-trigger .trigger:hover {
    color: #1890ff;
  }

  .ant-dropdown-menu-item {
    .tools-item-icon {
      margin-right: 10px !important;
    }
  }
</style>
